//===--- GenReflection.cpp - IR generation for nominal type reflection ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements IR generation of type metadata for struct/class
//  stored properties and enum cases for use with reflection.
//===----------------------------------------------------------------------===//

#include "polarphp/ast/Decl.h"
#include "polarphp/ast/GenericEnvironment.h"
#include "polarphp/ast/IRGenOptions.h"
#include "polarphp/ast/PrettyStackTrace.h"
#include "polarphp/ast/InterfaceConformance.h"
#include "polarphp/ast/SubstitutionMap.h"
#include "polarphp/basic/Platform.h"
#include "polarphp/irgen/Linking.h"
#include "polarphp/reflection/MetadataSourceBuilder.h"
#include "polarphp/reflection/Records.h"
#include "polarphp/pil/lang/PILModule.h"

#include "polarphp/irgen/internal/ConstantBuilder.h"
#include "polarphp/irgen/internal/Explosion.h"
#include "polarphp/irgen/internal/GenClass.h"
#include "polarphp/irgen/internal/GenDecl.h"
#include "polarphp/irgen/internal/GenEnum.h"
#include "polarphp/irgen/internal/GenHeap.h"
#include "polarphp/irgen/internal/GenInterface.h"
#include "polarphp/irgen/internal/GenType.h"
#include "polarphp/irgen/internal/IRGenDebugInfo.h"
#include "polarphp/irgen/internal/IRGenFunction.h"
#include "polarphp/irgen/internal/IRGenMangler.h"
#include "polarphp/irgen/internal/IRGenModule.h"
#include "polarphp/irgen/internal/LoadableTypeInfo.h"
#include "polarphp/irgen/internal/MetadataRequest.h"

using namespace polar;
using namespace irgen;
using namespace reflection;

class MetadataSourceEncoder
   : public MetadataSourceVisitor<MetadataSourceEncoder> {
   llvm::raw_ostream &OS;
public:
   MetadataSourceEncoder(llvm::raw_ostream &OS) : OS(OS) {}

   void
   visitClosureBindingMetadataSource(const ClosureBindingMetadataSource *CB) {
      OS << 'B';
      OS << CB->getIndex();
   }

   void
   visitReferenceCaptureMetadataSource(const ReferenceCaptureMetadataSource *RC){
      OS << 'R';
      OS << RC->getIndex();
   }

   void
   visitMetadataCaptureMetadataSource(const MetadataCaptureMetadataSource *MC) {
      OS << 'M';
      OS << MC->getIndex();
   }

   void
   visitGenericArgumentMetadataSource(const GenericArgumentMetadataSource *GA) {
      OS << 'G';
      OS << GA->getIndex();
      visit(GA->getSource());
      OS << '_';
   }

   void visitSelfMetadataSource(const SelfMetadataSource *S) {
      OS << 'S';
   }

   void
   visitSelfWitnessTableMetadataSource(const SelfWitnessTableMetadataSource *S) {
      OS << 'W';
   }
};

class PrintMetadataSource
   : public MetadataSourceVisitor<PrintMetadataSource, void> {
   llvm::raw_ostream &OS;
   unsigned Indent;

   llvm::raw_ostream &indent(unsigned Amount) {
      for (unsigned i = 0; i < Amount; ++i)
         OS << ' ';
      return OS;
   }

   llvm::raw_ostream &printHeader(std::string Name) {
      indent(Indent) << '(' << Name;
      return OS;
   }

   template<typename T>
   llvm::raw_ostream &printField(std::string name, const T &value) {
      if (!name.empty())
         OS << " " << name << "=" << value;
      else
         OS << " " << value;
      return OS;
   }

   void printRec(const reflection::MetadataSource *MS) {
      OS << "\n";

      Indent += 2;
      visit(MS);
      Indent -= 2;
   }

   void closeForm() {
      OS << ')';
   }

public:
   PrintMetadataSource(llvm::raw_ostream &OS, unsigned Indent)
      : OS(OS), Indent(Indent) {}

   void
   visitClosureBindingMetadataSource(const ClosureBindingMetadataSource *CB) {
      printHeader("closure-binding");
      printField("index", CB->getIndex());
      closeForm();
   }

   void
   visitReferenceCaptureMetadataSource(const ReferenceCaptureMetadataSource *RC){
      printHeader("reference-capture");
      printField("index", RC->getIndex());
      closeForm();
   }

   void
   visitMetadataCaptureMetadataSource(const MetadataCaptureMetadataSource *MC){
      printHeader("metadata-capture");
      printField("index", MC->getIndex());
      closeForm();
   }

   void
   visitGenericArgumentMetadataSource(const GenericArgumentMetadataSource *GA) {
      printHeader("generic-argument");
      printField("index", GA->getIndex());
      printRec(GA->getSource());
      closeForm();
   }

   void
   visitSelfMetadataSource(const SelfMetadataSource *S) {
      printHeader("self");
      closeForm();
   }

   void
   visitSelfWitnessTableMetadataSource(const SelfWitnessTableMetadataSource *S) {
      printHeader("self-witness-table");
      closeForm();
   }
};

// Return the minimum Swift runtime version that supports demangling a given
// type.
static llvm::VersionTuple
getRuntimeVersionThatSupportsDemanglingType(IRGenModule &IGM,
                                            CanType type) {
   // Associated types of opaque types weren't mangled in a usable form by the
   // Swift 5.1 runtime, so we needed to add a new mangling in 5.2.
   if (type->hasOpaqueArchetype()) {
      auto hasOpaqueAssocType = type.findIf([](CanType t) -> bool {
         if (auto a = dyn_cast<NestedArchetypeType>(t)) {
            return isa<OpaqueTypeArchetypeType>(a->getRoot());
         }
         return false;
      });

      if (hasOpaqueAssocType)
         return llvm::VersionTuple(5, 2);
      // Although opaque types in general were only added in Swift 5.1,
      // declarations that use them are already covered by availability
      // guards, so we don't need to limit availability of mangled names
      // involving them.
   }

   return llvm::VersionTuple(5, 0);
}

// Produce a fallback mangled type name that uses an open-coded callback
// to form the metadata. This is useful for working around bugs in older
// runtimes, or supporting new type system features when deploying back.
//
// Note that this functionality is limited, because the demangler callback
// mechanism can only produce complete metadata. It can't be used in situations
// where completing the metadata during demangling might cause cyclic
// dependencies.
static std::pair<llvm::Constant *, unsigned>
getTypeRefByFunction(IRGenModule &IGM,
                     CanGenericSignature sig,
                     CanType t) {
   IRGenMangler mangler;
   std::string symbolName =
      mangler.mangleSymbolNameForMangledMetadataAccessorString(
         "get_type_metadata", sig, t);
   auto constant = IGM.getAddrOfStringForMetadataRef(symbolName, /*align*/2,
      /*low bit*/false,
                                                     [&](ConstantInitBuilder &B) {
                                                        llvm::Function *accessor;

                                                        // Otherwise, we need to emit a helper function to bind the arguments
                                                        // out of the demangler's argument buffer.
                                                        auto fnTy = llvm::FunctionType::get(IGM.TypeMetadataPtrTy,
                                                                                            {IGM.Int8PtrTy}, /*vararg*/ false);
                                                        accessor =
                                                           llvm::Function::Create(fnTy, llvm::GlobalValue::PrivateLinkage,
                                                                                  symbolName, IGM.getModule());
                                                        accessor->setAttributes(IGM.constructInitialAttributes());

                                                        SmallVector<GenericRequirement, 4> requirements;
                                                        GenericEnvironment *genericEnv = nullptr;
                                                        if (sig) {
                                                           enumerateGenericSignatureRequirements(sig,
                                                                                                 [&](GenericRequirement reqt) { requirements.push_back(reqt); });
                                                           genericEnv = sig->getGenericEnvironment();
                                                        }

                                                        {
                                                           IRGenFunction IGF(IGM, accessor);
                                                           if (IGM.DebugInfo)
                                                              IGM.DebugInfo->emitArtificialFunction(IGF, accessor);

                                                           auto bindingsBufPtr = IGF.collectParameters().claimNext();

                                                           auto substT = genericEnv
                                                                         ? genericEnv->mapTypeIntoContext(t)->getCanonicalType()
                                                                         : t;

                                                           bindFromGenericRequirementsBuffer(IGF, requirements,
                                                                                             Address(bindingsBufPtr, IGM.getPointerAlignment()),
                                                                                             MetadataState::Complete,
                                                                                             [&](CanType t) {
                                                                                                return genericEnv
                                                                                                       ? genericEnv->mapTypeIntoContext(t)->getCanonicalType()
                                                                                                       : t;
                                                                                             });

                                                           auto ret = IGF.emitTypeMetadataRef(substT);
                                                           IGF.Builder.CreateRet(ret);
                                                        }
                                                        // Form the mangled name with its relative reference.
                                                        auto S = B.beginStruct();
                                                        S.setPacked(true);
                                                        S.add(llvm::ConstantInt::get(IGM.Int8Ty, 255));
                                                        S.add(llvm::ConstantInt::get(IGM.Int8Ty, 9));
                                                        S.addRelativeAddress(accessor);

                                                        // And a null terminator!
                                                        S.addInt(IGM.Int8Ty, 0);

                                                        return S.finishAndCreateFuture();
                                                     });
   return {constant, 6};
}

static std::pair<llvm::Constant *, unsigned>
getTypeRefImpl(IRGenModule &IGM,
               CanType type,
               CanGenericSignature sig,
               MangledTypeRefRole role) {
   switch (role) {
      case MangledTypeRefRole::DefaultAssociatedTypeWitness:
      case MangledTypeRefRole::Metadata:
         // Note that we're using all of the nominal types referenced by this type,
         // ensuring that we can always reconstruct type metadata from a mangled name
         // in-process.
         IGM.IRGen.noteUseOfTypeMetadata(type);

         // If the minimum deployment target's runtime demangler wouldn't understand
         // this mangled name, then fall back to generating a "mangled name" with a
         // symbolic reference with a callback function.
         if (auto runtimeCompatVersion = get_runtime_compatibility_version_for_target
            (IGM.Context.LangOpts.Target)) {
            if (*runtimeCompatVersion <
                getRuntimeVersionThatSupportsDemanglingType(IGM, type)) {
               return getTypeRefByFunction(IGM, sig, type);
            }
         }

         break;

      case MangledTypeRefRole::Reflection:
         // For reflection records only used for out-of-process reflection, we do not
         // need to force emission of runtime type metadata.
         IGM.IRGen.noteUseOfFieldDescriptors(type);
         break;
   }

   IRGenMangler Mangler;
   auto SymbolicName = Mangler.mangleTypeForReflection(IGM, type);
   return {IGM.getAddrOfStringForTypeRef(SymbolicName, role),
           SymbolicName.runtimeSizeInBytes()};
}

std::pair<llvm::Constant *, unsigned>
IRGenModule::getTypeRef(CanType type, CanGenericSignature sig,
                        MangledTypeRefRole role) {
   type = substOpaqueTypesWithUnderlyingTypes(type);
   return getTypeRefImpl(*this, type, sig, role);
}

std::pair<llvm::Constant *, unsigned>
IRGenModule::getTypeRef(Type type, GenericSignature genericSig,
                        MangledTypeRefRole role) {
   return getTypeRef(type->getCanonicalType(genericSig),
                     genericSig ? genericSig->getCanonicalSignature() : CanGenericSignature(),
                     role);
}

std::pair<llvm::Constant *, unsigned>
IRGenModule::getLoweredTypeRef(PILType loweredType,
                               CanGenericSignature genericSig,
                               MangledTypeRefRole role) {
   auto substTy =
      substOpaqueTypesWithUnderlyingTypes(loweredType, genericSig);
   auto type = substTy.getAstType();
   if (substTy.hasArchetype())
      type = type->mapTypeOutOfContext()->getCanonicalType();

   return getTypeRefImpl(*this, type, genericSig, role);
}

/// Emit a mangled string referencing a specific protocol conformance, so that
/// the runtime can fetch its witness table.
///
/// TODO: Currently this uses a stub mangling that just refers to an accessor
/// function. We need to fully develop the mangling with the ability to refer
/// to dependent conformances to be able to use mangled strings.
llvm::Constant *
IRGenModule::emitWitnessTableRefString(CanType type,
                                       InterfaceConformanceRef conformance,
                                       GenericSignature origGenericSig,
                                       bool shouldSetLowBit) {
   std::tie(type, conformance)
      = substOpaqueTypesWithUnderlyingTypes(type, conformance);

   auto origType = type;
   CanGenericSignature genericSig;
   SmallVector<GenericRequirement, 4> requirements;
   GenericEnvironment *genericEnv = nullptr;

   if (origGenericSig) {
      genericSig = origGenericSig->getCanonicalSignature();
      enumerateGenericSignatureRequirements(genericSig,
                                            [&](GenericRequirement reqt) { requirements.push_back(reqt); });
      genericEnv = genericSig->getGenericEnvironment();
   }

   IRGenMangler mangler;
   std::string symbolName =
      mangler.mangleSymbolNameForMangledConformanceAccessorString(
         "get_witness_table", genericSig, type, conformance);

   return getAddrOfStringForMetadataRef(symbolName, /*alignment=*/2,
                                        shouldSetLowBit,
                                        [&](ConstantInitBuilder &B) {
                                           // Build a stub that loads the necessary bindings from the key path's
                                           // argument buffer then fetches the metadata.
                                           auto fnTy = llvm::FunctionType::get(WitnessTablePtrTy,
                                                                               {Int8PtrTy}, /*vararg*/ false);
                                           auto accessorThunk =
                                              llvm::Function::Create(fnTy, llvm::GlobalValue::PrivateLinkage,
                                                                     symbolName, getModule());
                                           accessorThunk->setAttributes(constructInitialAttributes());

                                           {
                                              IRGenFunction IGF(*this, accessorThunk);
                                              if (DebugInfo)
                                                 DebugInfo->emitArtificialFunction(IGF, accessorThunk);

                                              if (type->hasTypeParameter()) {
                                                 auto bindingsBufPtr = IGF.collectParameters().claimNext();

                                                 bindFromGenericRequirementsBuffer(IGF, requirements,
                                                                                   Address(bindingsBufPtr, getPointerAlignment()),
                                                                                   MetadataState::Complete,
                                                                                   [&](CanType t) {
                                                                                      return genericEnv->mapTypeIntoContext(t)->getCanonicalType();
                                                                                   });

                                                 type = genericEnv->mapTypeIntoContext(type)->getCanonicalType();
                                              }
                                              if (origType->hasTypeParameter()) {
                                                 auto origSig = genericEnv->getGenericSignature();
                                                 conformance = conformance.subst(origType,
                                                                                 QueryInterfaceTypeSubstitutions(genericEnv),
                                                                                 LookUpConformanceInSignature(origSig.getPointer()));
                                              }
                                              auto ret = emitWitnessTableRef(IGF, type, conformance);
                                              IGF.Builder.CreateRet(ret);
                                           }

                                           // Form the mangled name with its relative reference.
                                           auto S = B.beginStruct();
                                           S.setPacked(true);
                                           S.add(llvm::ConstantInt::get(Int8Ty, 255));
                                           S.add(llvm::ConstantInt::get(Int8Ty, 9));
                                           S.addRelativeAddress(accessorThunk);

                                           // And a null terminator!
                                           S.addInt(Int8Ty, 0);

                                           return S.finishAndCreateFuture();
                                        });
}


llvm::Constant *IRGenModule::getMangledAssociatedConformance(
   const NormalInterfaceConformance *conformance,
   const AssociatedConformance &requirement) {
   // Figure out the name of the symbol to be used for the conformance.
   IRGenMangler mangler;
   auto symbolName =
      mangler.mangleSymbolNameForAssociatedConformanceWitness(
         conformance, requirement.getAssociation(),
         requirement.getAssociatedRequirement());

   // See if we emitted the constant already.
   auto &entry = StringsForTypeRef[symbolName];
   if (entry.second) {
      return entry.second;
   }

   // Get the accessor for this associated conformance.
   llvm::Function *accessor;
   unsigned char kind;
   if (conformance) {
      kind = 7;
      accessor = getAddrOfAssociatedTypeWitnessTableAccessFunction(conformance,
                                                                   requirement);
   } else {
      kind = 8;
      accessor = getAddrOfDefaultAssociatedConformanceAccessor(requirement);
   }

   // Form the mangled name with its relative reference.
   ConstantInitBuilder B(*this);
   auto S = B.beginStruct();
   S.setPacked(true);
   S.add(llvm::ConstantInt::get(Int8Ty, 255));
   S.add(llvm::ConstantInt::get(Int8Ty, kind));
   S.addRelativeAddress(accessor);

   // And a null terminator!
   S.addInt(Int8Ty, 0);

   auto finished = S.finishAndCreateFuture();
   auto var = new llvm::GlobalVariable(Module, finished.getType(),
      /*constant*/ true,
                                       llvm::GlobalValue::LinkOnceODRLinkage,
                                       nullptr,
                                       symbolName);
   ApplyIRLinkage(IRLinkage::InternalLinkOnceODR).to(var);
   var->setAlignment(2);
   setTrueConstGlobal(var);
   var->setSection(getReflectionTypeRefSectionName());

   finished.installInGlobal(var);

   // Drill down to the i8* at the beginning of the constant.
   auto addr = llvm::ConstantExpr::getBitCast(var, Int8PtrTy);

   // Set the low bit.
   unsigned bit = InterfaceRequirementFlags::AssociatedTypeMangledNameBit;
   auto bitConstant = llvm::ConstantInt::get(IntPtrTy, bit);
   addr = llvm::ConstantExpr::getGetElementPtr(nullptr, addr, bitConstant);

   // Update the entry.
   entry = {var, addr};

   return addr;
}

class ReflectionMetadataBuilder {
protected:
   IRGenModule &IGM;
   ConstantInitBuilder InitBuilder;
   ConstantStructBuilder B;

   ReflectionMetadataBuilder(IRGenModule &IGM)
      : IGM(IGM), InitBuilder(IGM), B(InitBuilder.beginStruct()) {}

   virtual ~ReflectionMetadataBuilder() {}

   // Collect any builtin types referenced from this type.
   void addBuiltinTypeRefs(CanType type) {
      if (IGM.getPolarphpModule()->isStdlibModule()) {
         type.visit([&](CanType t) {
            if (isa<BuiltinType>(t))
               IGM.BuiltinTypes.insert(t);
         });
      }
   }

   /// Add a 32-bit relative offset to a mangled typeref string
   /// in the typeref reflection section.
   ///
   /// By default, we use MangledTypeRefRole::Reflection, which does not
   /// force emission of any type metadata referenced from the typeref.
   ///
   /// For reflection records which are demangled to produce type metadata
   /// in-process, pass MangledTypeRefRole::Metadata instead.
   void addTypeRef(Type type, GenericSignature genericSig,
                   MangledTypeRefRole role =
                   MangledTypeRefRole::Reflection) {
      addTypeRef(type->getCanonicalType(genericSig),
                 genericSig ? genericSig->getCanonicalSignature()
                            : CanGenericSignature(),
                 role);
   }

   /// Add a 32-bit relative offset to a mangled typeref string
   /// in the typeref reflection section.
   ///
   /// By default, we use MangledTypeRefRole::Reflection, which does not
   /// force emission of any type metadata referenced from the typeref.
   ///
   /// For reflection records which are demangled to produce type metadata
   /// in-process, pass MangledTypeRefRole::Metadata instead.
   void addTypeRef(CanType type,
                   CanGenericSignature sig,
                   MangledTypeRefRole role =
                   MangledTypeRefRole::Reflection) {
      B.addRelativeAddress(IGM.getTypeRef(type, sig, role).first);
      addBuiltinTypeRefs(type);
   }

   void
   addLoweredTypeRef(PILType loweredType,
                     CanGenericSignature genericSig,
                     MangledTypeRefRole role = MangledTypeRefRole::Reflection) {
      B.addRelativeAddress(
         IGM.getLoweredTypeRef(loweredType, genericSig, role).first);
      addBuiltinTypeRefs(loweredType.getAstType());
   }

   /// Add a 32-bit relative offset to a mangled nominal type string
   /// in the typeref reflection section.
   ///
   /// See above comment about 'role'.
   void addNominalRef(const NominalTypeDecl *nominal,
                      MangledTypeRefRole role =
                      MangledTypeRefRole::Reflection) {
      if (auto proto = dyn_cast<InterfaceDecl>(nominal)) {
         IRGenMangler mangler;
         SymbolicMangling mangledStr;
         mangledStr.String = mangler.mangleBareInterface(proto);
         auto mangledName =
            IGM.getAddrOfStringForTypeRef(mangledStr, role);
         B.addRelativeAddress(mangledName);
      } else {
         addTypeRef(nominal->getDeclaredType(), GenericSignature(), role);
      }
   }

   // A function signature for a lambda wrapping an IRGenModule::getAddrOf*
   // method.
   using GetAddrOfEntityFn = llvm::Constant* (IRGenModule &, ConstantInit);

   llvm::GlobalVariable *emit(
      Optional<llvm::function_ref<GetAddrOfEntityFn>> getAddr,
      const char *section) {
      layout();

      llvm::GlobalVariable *var;

      // Some reflection records have a mangled symbol name, for uniquing
      // imported type metadata.
      if (getAddr) {
         auto init = B.finishAndCreateFuture();

         var = cast<llvm::GlobalVariable>((*getAddr)(IGM, init));
         var->setConstant(true);
         // Others, such as capture descriptors, do not have a name.
      } else {
         var = B.finishAndCreateGlobal("\x01l__swift5_reflection_descriptor",
                                       Alignment(4), /*isConstant*/ true,
                                       llvm::GlobalValue::PrivateLinkage);
      }

      var->setSection(section);

      IGM.addUsedGlobal(var);

      disableAddressSanitizer(IGM, var);

      return var;
   }

   // Helpers to guide the C++ type system into converting lambda arguments
   // to Optional<function_ref>
   llvm::GlobalVariable *emit(llvm::function_ref<GetAddrOfEntityFn> getAddr,
                              const char *section) {
      return emit(Optional<llvm::function_ref<GetAddrOfEntityFn>>(getAddr),
                  section);
   }
   llvm::GlobalVariable *emit(NoneType none,
                              const char *section) {
      return emit(Optional<llvm::function_ref<GetAddrOfEntityFn>>(),
                  section);
   }

   virtual void layout() = 0;
};

class AssociatedTypeMetadataBuilder : public ReflectionMetadataBuilder {
   static const uint32_t AssociatedTypeRecordSize = 8;

   const InterfaceConformance *Conformance;
   ArrayRef<std::pair<StringRef, CanType>> AssociatedTypes;

   void layout() override {
      // If the conforming type is generic, we just want to emit the
      // unbound generic type here.
      auto *Nominal = Conformance->getType()->getAnyNominal();
      assert(Nominal && "Structural conformance?");

      PrettyStackTraceDecl DebugStack("emitting associated type metadata",
                                      Nominal);

      addNominalRef(Nominal);
      addNominalRef(Conformance->getInterface());

      B.addInt32(AssociatedTypes.size());
      B.addInt32(AssociatedTypeRecordSize);

      for (auto AssocTy : AssociatedTypes) {
         auto NameGlobal = IGM.getAddrOfFieldName(AssocTy.first);
         B.addRelativeAddress(NameGlobal);
         addTypeRef(AssocTy.second,
                    Nominal->getGenericSignature()
                    ? Nominal->getGenericSignature()->getCanonicalSignature()
                    : CanGenericSignature());
      }
   }

public:
   AssociatedTypeMetadataBuilder(IRGenModule &IGM,
                                 const InterfaceConformance *Conformance,
                                 ArrayRef<std::pair<StringRef, CanType>> AssociatedTypes)
      : ReflectionMetadataBuilder(IGM), Conformance(Conformance),
        AssociatedTypes(AssociatedTypes) {}

   llvm::GlobalVariable *emit() {
      auto section = IGM.getAssociatedTypeMetadataSectionName();
      return ReflectionMetadataBuilder::emit(
         [&](IRGenModule &IGM, ConstantInit init) -> llvm::Constant* {
            return IGM.getAddrOfReflectionAssociatedTypeDescriptor(Conformance,init);
         },
         section);
   }
};

class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
   const uint32_t fieldRecordSize = 12;
   const NominalTypeDecl *NTD;

   void addFieldDecl(const ValueDecl *value, Type type,
                     GenericSignature genericSig, bool indirect=false) {
      reflection::FieldRecordFlags flags;
      flags.setIsIndirectCase(indirect);
      if (auto var = dyn_cast<VarDecl>(value))
         flags.setIsVar(!var->isLet());

      B.addInt32(flags.getRawValue());

      if (!type) {
         B.addInt32(0);
      } else {
         // The standard library's Mirror demangles metadata from field
         // descriptors, so use MangledTypeRefRole::Metadata to ensure
         // runtime metadata is available.
         addTypeRef(type, genericSig, MangledTypeRefRole::Metadata);
      }

      if (IGM.IRGen.Opts.EnableReflectionNames) {
         auto name = value->getBaseName().getIdentifier().str();
         auto fieldName = IGM.getAddrOfFieldName(name);
         B.addRelativeAddress(fieldName);
      } else {
         B.addInt32(0);
      }
   }

   void layoutRecord() {
      auto kind = FieldDescriptorKind::Struct;

      if (auto CD = dyn_cast<ClassDecl>(NTD)) {
         auto type = CD->getDeclaredType()->getCanonicalType();
         auto RC = type->getReferenceCounting();
         // @todo
//         if (RC == ReferenceCounting::ObjC)
//            kind = FieldDescriptorKind::ObjCClass;
//         else
         kind = FieldDescriptorKind::Class;
      }

      B.addInt16(uint16_t(kind));
      B.addInt16(fieldRecordSize);

      auto properties = NTD->getStoredProperties();
      B.addInt32(properties.size());
      for (auto property : properties)
         addFieldDecl(property, property->getInterfaceType(),
                      NTD->getGenericSignature());
   }

   void layoutEnum() {
      auto enumDecl = cast<EnumDecl>(NTD);
      auto &strategy = irgen::getEnumImplStrategy(
         IGM, enumDecl->getDeclaredTypeInContext()
            ->getCanonicalType());

      auto kind = FieldDescriptorKind::Enum;

      if (strategy.getElementsWithPayload().size() > 1 &&
          !strategy.needsPayloadSizeInMetadata()) {
         kind = FieldDescriptorKind::MultiPayloadEnum;
      }

      B.addInt16(uint16_t(kind));
      B.addInt16(fieldRecordSize);
      B.addInt32(strategy.getElementsWithPayload().size()
                 + strategy.getElementsWithNoPayload().size());

      for (auto enumCase : strategy.getElementsWithPayload()) {
         bool indirect = (enumCase.decl->isIndirect() ||
                          enumDecl->isIndirect());
         addFieldDecl(enumCase.decl, enumCase.decl->getArgumentInterfaceType(),
                      enumDecl->getGenericSignature(),
                      indirect);
      }

      for (auto enumCase : strategy.getElementsWithNoPayload()) {
         addFieldDecl(enumCase.decl, CanType(), nullptr);
      }
   }

   void layoutInterface() {
      auto PD = cast<InterfaceDecl>(NTD);
      FieldDescriptorKind Kind;
      /*if (PD->isObjC())
         Kind = FieldDescriptorKind::ObjCInterface;
      else */if (PD->requiresClass())
         Kind = FieldDescriptorKind::ClassInterface;
      else
         Kind = FieldDescriptorKind::Interface;
      B.addInt16(uint16_t(Kind));
      B.addInt16(fieldRecordSize);
      B.addInt32(0);
   }

   void layout() override {
      if (NTD->hasClangNode()) {
         auto *enumDecl = dyn_cast<EnumDecl>(NTD);
         // Structs and namespace-like enums are ok.
         assert(isa<StructDecl>(NTD) || (enumDecl && !enumDecl->hasCases()));
      }

      PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD);
      addNominalRef(NTD);

      auto *CD = dyn_cast<ClassDecl>(NTD);
      auto *PD = dyn_cast<InterfaceDecl>(NTD);
      if (CD && CD->getSuperclass()) {
         addTypeRef(CD->getSuperclass(), CD->getGenericSignature());
      } else if (PD && PD->getDeclaredType()->getSuperclass()) {
         addTypeRef(PD->getDeclaredType()->getSuperclass(),
                    PD->getGenericSignature());
      } else {
         B.addInt32(0);
      }

      switch (NTD->getKind()) {
         case DeclKind::Class:
         case DeclKind::Struct:
            layoutRecord();
            break;

         case DeclKind::Enum:
            layoutEnum();
            break;

         case DeclKind::Interface:
            layoutInterface();
            break;

         default:
            llvm_unreachable("Not a nominal type");
            break;
      }
   }

public:
   FieldTypeMetadataBuilder(IRGenModule &IGM,
                            const NominalTypeDecl * NTD)
      : ReflectionMetadataBuilder(IGM), NTD(NTD) {}

   llvm::GlobalVariable *emit() {
      auto section = IGM.getFieldTypeMetadataSectionName();
      return ReflectionMetadataBuilder::emit(
         [&](IRGenModule &IGM, ConstantInit definition) -> llvm::Constant* {
            return IGM.getAddrOfReflectionFieldDescriptor(
               NTD->getDeclaredType()->getCanonicalType(), definition);
         },
         section);
   }
};

class FixedTypeMetadataBuilder : public ReflectionMetadataBuilder {
   ModuleDecl *module;
   CanType type;
   const FixedTypeInfo *ti;

public:
   FixedTypeMetadataBuilder(IRGenModule &IGM,
                            CanType builtinType)
      : ReflectionMetadataBuilder(IGM) {
      module = builtinType->getAstContext().TheBuiltinModule;
      type = builtinType;
      ti = &cast<FixedTypeInfo>(IGM.getTypeInfoForUnlowered(builtinType));
   }

   FixedTypeMetadataBuilder(IRGenModule &IGM,
                            const NominalTypeDecl *nominalDecl)
      : ReflectionMetadataBuilder(IGM) {
      module = nominalDecl->getParentModule();
      type = nominalDecl->getDeclaredType()->getCanonicalType();
      ti = &cast<FixedTypeInfo>(IGM.getTypeInfoForUnlowered(
         nominalDecl->getDeclaredTypeInContext()->getCanonicalType()));
   }

   void layout() override {
      if (type->isAnyObject()) {
         // AnyObject isn't actually a builtin type; we're emitting it as the old
         // Builtin.UnknownObject type for ABI compatibility.
         B.addRelativeAddress(
            IGM.getAddrOfStringForTypeRef("BO", MangledTypeRefRole::Reflection));
      } else {
         addTypeRef(type, CanGenericSignature());
      }

      B.addInt32(ti->getFixedSize().getValue());

      auto alignment = ti->getFixedAlignment().getValue();
      unsigned bitwiseTakable =
         (ti->isBitwiseTakable(ResilienceExpansion::Minimal) == IsBitwiseTakable
          ? 1 : 0);
      B.addInt32(alignment | (bitwiseTakable << 16));

      B.addInt32(ti->getFixedStride().getValue());
      B.addInt32(ti->getFixedExtraInhabitantCount(IGM));
   }

   llvm::GlobalVariable *emit() {
      auto section = IGM.getBuiltinTypeMetadataSectionName();
      return ReflectionMetadataBuilder::emit(
         [&](IRGenModule &IGM, ConstantInit definition) -> llvm::Constant * {
            return IGM.getAddrOfReflectionBuiltinDescriptor(type, definition);
         },
         section);
   }
};

void IRGenModule::emitBuiltinTypeMetadataRecord(CanType builtinType) {
   FixedTypeMetadataBuilder builder(*this, builtinType);
   builder.emit();
}

/// Builds a constant LLVM struct describing the layout of a fixed-size
/// PIL @box. These look like closure contexts, but without any necessary
/// bindings or metadata sources, and only a single captured value.
class BoxDescriptorBuilder : public ReflectionMetadataBuilder {
   PILType BoxedType;
   CanGenericSignature genericSig;
public:
   BoxDescriptorBuilder(IRGenModule &IGM, PILType BoxedType,
                        CanGenericSignature genericSig)
      : ReflectionMetadataBuilder(IGM), BoxedType(BoxedType),
        genericSig(genericSig) {}

   void layout() override {
      B.addInt32(1);
      B.addInt32(0); // Number of sources
      B.addInt32(0); // Number of generic bindings

      addLoweredTypeRef(BoxedType, genericSig);
   }

   llvm::GlobalVariable *emit() {
      auto section = IGM.getCaptureDescriptorMetadataSectionName();
      return ReflectionMetadataBuilder::emit(None, section);
   }
};

/// Builds a constant LLVM struct describing the layout of a heap closure,
/// the types of its captures, and the sources of metadata if any of the
/// captures are generic.
///
/// For now capture descriptors are only used by out-of-process reflection.
///
/// If the standard library's Mirror type ever gains the ability to reflect
/// closure contexts, we should use MangledTypeRefRole::Metadata below.
class CaptureDescriptorBuilder : public ReflectionMetadataBuilder {
   polar::reflection::MetadataSourceBuilder SourceBuilder;
   CanPILFunctionType OrigCalleeType;
   CanPILFunctionType SubstCalleeType;
   SubstitutionMap Subs;
   const HeapLayout &Layout;

public:
   CaptureDescriptorBuilder(IRGenModule &IGM,
                            CanPILFunctionType OrigCalleeType,
                            CanPILFunctionType SubstCalleeType,
                            SubstitutionMap Subs,
                            const HeapLayout &Layout)
      : ReflectionMetadataBuilder(IGM),
        OrigCalleeType(OrigCalleeType),
        SubstCalleeType(SubstCalleeType), Subs(Subs),
        Layout(Layout) {}

   using MetadataSourceMap
   = std::vector<std::pair<CanType, const reflection::MetadataSource*>>;

   void addMetadataSource(const reflection::MetadataSource *Source) {
      if (Source == nullptr) {
         B.addInt32(0);
      } else {
         SmallString<16> EncodeBuffer;
         llvm::raw_svector_ostream OS(EncodeBuffer);
         MetadataSourceEncoder Encoder(OS);
         Encoder.visit(Source);

         auto EncodedSource =
            IGM.getAddrOfStringForTypeRef(OS.str(), MangledTypeRefRole::Reflection);
         B.addRelativeAddress(EncodedSource);
      }
   }

   /// Give up if we captured an opened existential type. Eventually we
   /// should figure out how to represent this.
   static bool hasOpenedExistential(CanPILFunctionType OrigCalleeType,
                                    const HeapLayout &Layout) {
      if (!OrigCalleeType->isPolymorphic() ||
          OrigCalleeType->isPseudogeneric())
         return false;

      auto &Bindings = Layout.getBindings();
      for (unsigned i = 0; i < Bindings.size(); ++i) {
         // Skip protocol requirements (FIXME: for now?)
         if (Bindings[i].Interface != nullptr)
            continue;

         if (Bindings[i].TypeParameter->hasOpenedExistential())
            return true;
      }

      auto ElementTypes = Layout.getElementTypes().slice(
         Layout.hasBindings() ? 1 : 0);
      for (auto ElementType : ElementTypes) {
         auto SwiftType = ElementType.getAstType();
         if (SwiftType->hasOpenedExistential())
            return true;
      }

      return false;
   }

   /// Slice off the NecessaryBindings struct at the beginning, if it's there.
   /// We'll keep track of how many things are in the bindings struct with its
   /// own count in the capture descriptor.
   ArrayRef<PILType> getElementTypes() {
      return Layout.getElementTypes().slice(Layout.hasBindings() ? 1 : 0);
   }

   /// Build a map from generic parameter -> source of its metadata at runtime.
   ///
   /// If the callee that we are partially applying to create a box/closure
   /// isn't generic, then the map is empty.
   MetadataSourceMap getMetadataSourceMap() {
      MetadataSourceMap SourceMap;

      // Generic parameters of pseudogeneric functions do not have
      // runtime metadata.
      if (!OrigCalleeType->isPolymorphic() ||
          OrigCalleeType->isPseudogeneric())
         return SourceMap;

      // Any generic parameters that are not fulfilled are passed in via the
      // bindings. Structural types are decomposed, so emit the contents of
      // the bindings structure directly.
      auto &Bindings = Layout.getBindings();
      for (unsigned i = 0; i < Bindings.size(); ++i) {
         // Skip protocol requirements (FIXME: for now?)
         if (Bindings[i].Interface != nullptr)
            continue;

         auto Source = SourceBuilder.createClosureBinding(i);
         auto BindingType = Bindings[i].TypeParameter;
         auto InterfaceType = BindingType->mapTypeOutOfContext();
         SourceMap.push_back({InterfaceType->getCanonicalType(), Source});
      }

      // Check if any requirements were fulfilled by metadata stored inside a
      // captured value.

      enumerateGenericParamFulfillments(IGM, OrigCalleeType,
                                        [&](CanType GenericParam,
                                            const irgen::MetadataSource &Source,
                                            const MetadataPath &Path) {

                                           const reflection::MetadataSource *Root;
                                           switch (Source.getKind()) {
                                              case irgen::MetadataSource::Kind::SelfMetadata:
                                              case irgen::MetadataSource::Kind::SelfWitnessTable:
                                                 // Handled as part of bindings
                                                 return;

                                              case irgen::MetadataSource::Kind::GenericLValueMetadata:
                                                 // FIXME?
                                                 return;

                                              case irgen::MetadataSource::Kind::ClassPointer:
                                                 Root = SourceBuilder.createReferenceCapture(Source.getParamIndex());
                                                 break;

                                              case irgen::MetadataSource::Kind::Metadata:
                                                 Root = SourceBuilder.createMetadataCapture(Source.getParamIndex());
                                                 break;
                                           }

                                           // The metadata might be reached via a non-trivial path (eg,
                                           // dereferencing an isa pointer or a generic argument). Record
                                           // the path. We assume captured values map 1-1 with function
                                           // parameters.
                                           auto Src = Path.getMetadataSource(SourceBuilder, Root);

                                           auto SubstType = GenericParam.subst(Subs);
                                           auto InterfaceType = SubstType->mapTypeOutOfContext();
                                           SourceMap.push_back({InterfaceType->getCanonicalType(), Src});
                                        });

      return SourceMap;
   }

   /// Get the interface types of all of the captured values, mapped out of the
   /// context of the callee we're partially applying.
   std::vector<PILType> getCaptureTypes() {
      std::vector<PILType> CaptureTypes;

      for (auto ElementType : getElementTypes()) {
         auto SwiftType = ElementType.getAstType();

         // Erase pseudogeneric captures down to AnyObject.
         if (OrigCalleeType->isPseudogeneric()) {
            SwiftType = SwiftType.transform([&](Type t) -> Type {
               if (auto *archetype = t->getAs<ArchetypeType>()) {
                  assert(archetype->requiresClass() && "don't know what to do");
                  return IGM.Context.getAnyObjectType();
               }
               return t;
            })->getCanonicalType();
         }

         CaptureTypes.push_back(
            PILType::getPrimitiveObjectType(SwiftType->getCanonicalType()));
      }

      return CaptureTypes;
   }

   void layout() override {
      auto CaptureTypes = getCaptureTypes();
      auto MetadataSources = getMetadataSourceMap();

      B.addInt32(CaptureTypes.size());
      B.addInt32(MetadataSources.size());
      B.addInt32(Layout.getBindings().size());

      auto sig = OrigCalleeType->getSubstGenericSignature()
                 ? OrigCalleeType->getSubstGenericSignature()
                    ->getCanonicalSignature()
                 : CanGenericSignature();

      // Now add typerefs of all of the captures.
      for (auto CaptureType : CaptureTypes) {
         addLoweredTypeRef(CaptureType, sig);
      }

      // Add the pairs that make up the generic param -> metadata source map
      // to the struct.
      for (auto GenericAndSource : MetadataSources) {
         auto GenericParam = GenericAndSource.first->getCanonicalType();
         auto Source = GenericAndSource.second;

         addTypeRef(GenericParam, sig);
         addMetadataSource(Source);
      }
   }

   llvm::GlobalVariable *emit() {
      auto section = IGM.getCaptureDescriptorMetadataSectionName();
      return ReflectionMetadataBuilder::emit(None, section);
   }
};

static std::string getReflectionSectionName(IRGenModule &IGM,
                                            StringRef LongName,
                                            StringRef FourCC) {
   SmallString<50> SectionName;
   llvm::raw_svector_ostream OS(SectionName);
   switch (IGM.TargetInfo.OutputObjectFormat) {
      case llvm::Triple::UnknownObjectFormat:
         llvm_unreachable("unknown object format");
      case llvm::Triple::XCOFF:
      case llvm::Triple::COFF:
         assert(FourCC.size() <= 4 &&
                "COFF section name length must be <= 8 characters");
         OS << ".sw5" << FourCC << "$B";
         break;
      case llvm::Triple::ELF:
      case llvm::Triple::Wasm:
         OS << "swift5_" << LongName;
         break;
      case llvm::Triple::MachO:
         assert(LongName.size() <= 7 &&
                "Mach-O section name length must be <= 16 characters");
         OS << "__TEXT,__swift5_" << LongName << ", regular, no_dead_strip";
         break;
   }
   return OS.str();
}

const char *IRGenModule::getFieldTypeMetadataSectionName() {
   if (FieldTypeSection.empty())
      FieldTypeSection = getReflectionSectionName(*this, "fieldmd", "flmd");
   return FieldTypeSection.c_str();
}

const char *IRGenModule::getBuiltinTypeMetadataSectionName() {
   if (BuiltinTypeSection.empty())
      BuiltinTypeSection = getReflectionSectionName(*this, "builtin", "bltn");
   return BuiltinTypeSection.c_str();
}

const char *IRGenModule::getAssociatedTypeMetadataSectionName() {
   if (AssociatedTypeSection.empty())
      AssociatedTypeSection = getReflectionSectionName(*this, "assocty", "asty");
   return AssociatedTypeSection.c_str();
}

const char *IRGenModule::getCaptureDescriptorMetadataSectionName() {
   if (CaptureDescriptorSection.empty())
      CaptureDescriptorSection = getReflectionSectionName(*this, "capture", "cptr");
   return CaptureDescriptorSection.c_str();
}

const char *IRGenModule::getReflectionStringsSectionName() {
   if (ReflectionStringsSection.empty())
      ReflectionStringsSection = getReflectionSectionName(*this, "reflstr", "rfst");
   return ReflectionStringsSection.c_str();
}

const char *IRGenModule::getReflectionTypeRefSectionName() {
   if (ReflectionTypeRefSection.empty())
      ReflectionTypeRefSection = getReflectionSectionName(*this, "typeref", "tyrf");
   return ReflectionTypeRefSection.c_str();
}

llvm::Constant *IRGenModule::getAddrOfFieldName(StringRef Name) {
   auto &entry = FieldNames[Name];
   if (entry.second)
      return entry.second;

   entry = createStringConstant(Name, /*willBeRelativelyAddressed*/ true,
                                getReflectionStringsSectionName());
   disableAddressSanitizer(*this, entry.first);
   return entry.second;
}

llvm::Constant *
IRGenModule::getAddrOfBoxDescriptor(PILType BoxedType,
                                    CanGenericSignature genericSig) {
   if (!IRGen.Opts.EnableReflectionMetadata)
      return llvm::Constant::getNullValue(CaptureDescriptorPtrTy);

   BoxDescriptorBuilder builder(*this, BoxedType, genericSig);
   auto var = builder.emit();

   return llvm::ConstantExpr::getBitCast(var, CaptureDescriptorPtrTy);
}

llvm::Constant *
IRGenModule::getAddrOfCaptureDescriptor(PILFunction &Caller,
                                        CanPILFunctionType OrigCalleeType,
                                        CanPILFunctionType SubstCalleeType,
                                        SubstitutionMap Subs,
                                        const HeapLayout &Layout) {
   if (!IRGen.Opts.EnableReflectionMetadata)
      return llvm::Constant::getNullValue(CaptureDescriptorPtrTy);

   if (CaptureDescriptorBuilder::hasOpenedExistential(OrigCalleeType, Layout))
      return llvm::Constant::getNullValue(CaptureDescriptorPtrTy);

   CaptureDescriptorBuilder builder(*this,
                                    OrigCalleeType, SubstCalleeType, Subs,
                                    Layout);
   auto var = builder.emit();
   return llvm::ConstantExpr::getBitCast(var, CaptureDescriptorPtrTy);
}

void IRGenModule::
emitAssociatedTypeMetadataRecord(const RootInterfaceConformance *conformance) {
   auto normalConf = dyn_cast<NormalInterfaceConformance>(conformance);
   if (!normalConf)
      return;

   if (!IRGen.Opts.EnableReflectionMetadata)
      return;

   SmallVector<std::pair<StringRef, CanType>, 2> AssociatedTypes;

   auto collectTypeWitness = [&](const AssociatedTypeDecl *AssocTy,
                                 Type Replacement,
                                 const TypeDecl *TD) -> bool {
      AssociatedTypes.push_back({
                                   AssocTy->getNameStr(),
                                   Replacement->getCanonicalType()
                                });
      return false;
   };

   normalConf->forEachTypeWitness(collectTypeWitness);

   // If there are no associated types, don't bother emitting any
   // metadata.
   if (AssociatedTypes.empty())
      return;

   AssociatedTypeMetadataBuilder builder(*this, normalConf, AssociatedTypes);
   builder.emit();
}

void IRGenModule::emitBuiltinReflectionMetadata() {
   if (getPolarphpModule()->isStdlibModule()) {
      BuiltinTypes.insert(Context.TheNativeObjectType);
      BuiltinTypes.insert(Context.getAnyObjectType());
      BuiltinTypes.insert(Context.TheBridgeObjectType);
      BuiltinTypes.insert(Context.TheRawPointerType);
      BuiltinTypes.insert(Context.TheUnsafeValueBufferType);

      // This would not be necessary if RawPointer had the same set of
      // extra inhabitants as these. But maybe it's best not to codify
      // that in the ABI anyway.
      CanType thinFunction = CanFunctionType::get(
         {}, Context.TheEmptyTupleType,
         AnyFunctionType::ExtInfo().withRepresentation(
            FunctionTypeRepresentation::Thin));
      BuiltinTypes.insert(thinFunction);

      CanType anyMetatype = CanExistentialMetatypeType::get(
         Context.TheAnyType);
      BuiltinTypes.insert(anyMetatype);
   }

   for (auto builtinType : BuiltinTypes)
      emitBuiltinTypeMetadataRecord(builtinType);
}

void IRGenerator::emitBuiltinReflectionMetadata() {
   for (auto &m : *this) {
      m.second->emitBuiltinReflectionMetadata();
   }
}

void IRGenModule::emitFieldDescriptor(const NominalTypeDecl *D) {
   if (!IRGen.Opts.EnableReflectionMetadata)
      return;

   auto T = D->getDeclaredTypeInContext()->getCanonicalType();

   bool needsOpaqueDescriptor = false;
   bool needsFieldDescriptor = true;

   if (auto *ED = dyn_cast<EnumDecl>(D)) {
      auto &strategy = getEnumImplStrategy(*this, T);

      // @objc enums never have generic parameters or payloads,
      // and lower as their raw type.
      if (!strategy.isReflectable()) {
         needsOpaqueDescriptor = true;
         needsFieldDescriptor = false;
      }

      // If this is a fixed-size multi-payload enum, we have to emit a descriptor
      // with the size and alignment of the type, because the reflection library
      // cannot derive this information at runtime.
      if (strategy.getElementsWithPayload().size() > 1 &&
          !strategy.needsPayloadSizeInMetadata()) {
         needsOpaqueDescriptor = true;
      }
   }

   if (auto *SD = dyn_cast<StructDecl>(D)) {
      if (SD->hasClangNode())
         needsOpaqueDescriptor = true;
   }

   // If the type has custom @_alignment, emit a fixed record with the
   // alignment since remote mirrors will need to treat the type as opaque.
   //
   // Note that we go on to also emit a field descriptor in this case,
   // since in-process reflection only cares about the types of the fields
   // and does not independently re-derive the layout.
   if (D->getAttrs().hasAttribute<AlignmentAttr>()) {
      auto &TI = getTypeInfoForUnlowered(T);
      if (isa<FixedTypeInfo>(TI)) {
         needsOpaqueDescriptor = true;
      }
   }

   if (needsOpaqueDescriptor) {
      FixedTypeMetadataBuilder builder(*this, D);
      builder.emit();
   }

   if (needsFieldDescriptor) {
      FieldTypeMetadataBuilder builder(*this, D);
      FieldDescriptors.push_back(builder.emit());
   }
}

void IRGenModule::emitReflectionMetadataVersion() {
   auto Init =
      llvm::ConstantInt::get(Int16Ty, POLARPHP_REFLECTION_METADATA_VERSION);
   auto Version = new llvm::GlobalVariable(Module, Int16Ty, /*constant*/ true,
                                           llvm::GlobalValue::LinkOnceODRLinkage,
                                           Init,
                                           "__polarphp_reflection_version");
   ApplyIRLinkage(IRLinkage::InternalLinkOnceODR).to(Version);
   addUsedGlobal(Version);
}

void IRGenerator::emitReflectionMetadataVersion() {
   for (auto &m : *this) {
      m.second->emitReflectionMetadataVersion();
   }
}
